<template>
  <div class="body_style">
    <PageTitle>
      <template slot="left">excel转json对象</template>
      <template slot="right">
        <a-button class="btn_margin" @click="copyCode">拷贝代码</a-button>
        <a-upload
          :showUploadList="false"
          :before-upload="beforeUpload"
          :accept="acceptRule.join(',')"
        >
          <a-button type="primary">导入文件</a-button>
        </a-upload>
        <a-button
          type="danger"
          @click="
            () => {
              this.fileList = [];
            }
          "
          class="btn_margin"
          >清除所有文件</a-button
        >
      </template>
    </PageTitle>

    <div class="content_box padding_box box_border">
      <div class="content_area">
        <div class="card_area">
          <div
            :class="[
              'card_style',
              'padding_box',
              'box_border',
              'border_shadow',
              index === selectXlsx ? 'card_style_black' : '',
            ]"
            v-for="(item, index) in fileList"
            :key="item.id"
            @click="changeTable(index)"
          >
            <div class="card_title beyond_hidden">{{ item.name }}</div>
            <div>
              共<span class="num_style">{{ item.SheetNames.length }}</span
              >张表
            </div>
            <div class="icon_style">
              <a-icon type="close" @click="delFile(item.id)" />
            </div>
          </div>
        </div>
        <template v-if="nowTab.length">
          <a-tabs v-model="tabKey">
            <a-tab-pane
              :tab="item"
              v-for="item in nowTab"
              :key="item"
            ></a-tab-pane>
          </a-tabs>
          <a-table :columns="columns" :dataSource="dataSource" rowKey="id">
          </a-table>
        </template>
      </div>
    </div>
    <CodeDrawer ref="codeDrawer" :codeArr="dataSource" />
  </div>
</template>

<script>
import XLSX, { utils } from "xlsx";
import { validAlphabets } from "@/utils/validate";
import PageTitle from "@/components/pageTitle/index.vue";
import CodeDrawer from "./components/codeDrawer.vue";
export default {
  name: "xlsxToJson",
  components: { PageTitle, CodeDrawer },
  data() {
    return {
      acceptRule: [
        "application/vnd.ms-excel",
        "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet",
      ],
      fileList: [],
      selectXlsx: 0,
      tabKey: undefined,
      codeArr: "",
    };
  },
  computed: {
    nowTab() {
      return this.fileList[this.selectXlsx]?.SheetNames || [];
    },
    columns() {
      let sheet = this.fileList[this.selectXlsx]?.sheet || undefined;
      let header = sheet ? sheet[this.tabKey][0] : undefined;
      return header
        ? Object.keys(header).map((item) => {
            return {
              title: item,
              dataIndex: item,
            };
          })
        : [];
    },
    dataSource() {
      return (
        this.fileList[this.selectXlsx]?.sheet[this.tabKey].map(
          (item, index) => {
            return {
              ...item,
              id: index,
            };
          }
        ) || []
      );
    },
  },
  methods: {
    copyCode() {
      if (this.dataSource.length) {
        this.$refs.codeDrawer.showDrawe();
      } else {
        this.$toast.fail("无代码需要复制");
      }
    },
    delFile(id) {
      this.fileList = this.fileList.filter((item) => item.id !== id);
    },
    changeTable(index) {
      this.selectXlsx = index;
    },
    beforeUpload(file) {
      if (this.acceptRule.indexOf(file.type) > -1) {
        this.importFromLocal(file).then((res) => {
          let data = {
            ...res,
            name: file.name,
            id: this.fileList.length
              ? this.fileList[this.fileList.length - 1].id + 1
              : 1,
          };
          this.tabKey = data.SheetNames[0];
          this.fileList.unshift(data);
        });
      }
      return false;
    },

    /**
     * @description  解析表格文件数据，返回表格中内容，目前暂不支持导入有单元格合并的表格
     * @param file 导入的文件，二进制数据流
     * @returns sheet 每张表的表数据
     * @returns sheetHeader 每张表的表头
     * @returns SheetNames 每张表的表名
     * @returns workBook 解析出的每张表的所有数据
     */
    async importFromLocal(file) {
      const workBook = await this.readerWorkBookFromLocal(file),
        data = {},
        sheet = {},
        sheetHeader = {};
      workBook.SheetNames.forEach((item) => {
        sheet[item] = utils.sheet_to_json(workBook.Sheets[item]);
        sheetHeader[item] = this.changeSheetHeader(workBook.Sheets[item]);
      });
      data.sheet = sheet;
      data.sheetHeader = sheetHeader;
      data.SheetNames = workBook.SheetNames;
      data.workBook = workBook;
      return data;
    },

    /**
     * @description 本地读取文件的方法
     * @param {Object} file 文件流
     */
    readerWorkBookFromLocal(file) {
      const reader = new FileReader();
      reader.readAsBinaryString(file);
      return new Promise(function (resolve, reject) {
        reader.onload = function (e) {
          const fileData = e.target.result;
          if (reader.readyState === 2) {
            // console.log("XLSX",XLSX)
            const workBook = XLSX.read(fileData, { type: "binary" });
            resolve(workBook);
          } else {
            reject("读取文件失败");
          }
        };
      });
    },

    /**
     * @description 取出表头
     */
    changeSheetHeader(sheets) {
      let arr = [];
      // 取出表格中所有表头
      let content = Object.keys(sheets);
      // 更新表头列表
      content.forEach((item) => {
        if (item.length === 2 && validAlphabets(item[0]) && item[1] == "1") {
          arr.push(sheets[item].v);
        }
      });
      return arr;
    },
  },
};
</script>

<style lang="less" scoped>
.btn_margin {
  margin: 0 20px;
}
.body_style {
  display: flex;
  flex-direction: column;
  height: 100%;

  .content_box {
    flex: 1;
    background-color: #fff;

    .content_area {
      height: 100%;
      overflow-y: scroll;

      .card_area {
        display: flex;
        flex-wrap: wrap;
        width: 100%;
      }

      .card_style {
        position: relative;
        margin-right: 1.25rem;
        font-size: 1rem;
        width: 20%;
        cursor: pointer;
        .card_title {
          font-size: 1.5rem;
          font-weight: bold;
        }
        .num_style {
          margin: 0 10px;
          font-size: 1.5rem;
          color: red;
        }
        .icon_style {
          position: absolute;
          right: 10px;
          top: 10px;
        }
      }

      .card_style_black {
        background: rgba(0, 0, 0, 0.9);
        color: #fff;
      }
    }
  }
}
</style>
